using System;
using System.Collections.Generic;
using System.Text;
using SystemFunctionLib.Apis;
using System.Drawing;

namespace SystemFunctionLib.Input
{
    public static class Mouse
    {
        private const uint NULL = 0;
        private const uint TRUE = 1;
        private const uint FALSE = 0;

        /// <summary>
        /// Gets or sets the height, in pixels, of the rectangle within which the mouse pointer has 
        /// to stay for generating mouse hover event.
        /// </summary>
        public unsafe static int HoverHeight
        {
            get
            {
                uint height = 0;
                WinApis.SystemParametersInfo(
                    SPI.GetMouseHoverHeight,
                    NULL,
                    (void*)&height,
                    SPIF.None);

                return (int)height;
            }
            set
            {
                WinApis.SystemParametersInfo(
                    SPI.SetMouseHoverHeight,
                    (uint)value,
                    NULL,
                    SPIF.SendChange);
            }
        }

        /// <summary>
        /// Gets or sets the width, in pixels, of the rectangle within which the mouse pointer has 
        /// to stay for generating mouse hover event.
        /// </summary>
        public unsafe static int HoverWidth
        {
            get
            {
                uint width = 0;
                WinApis.SystemParametersInfo(
                    SPI.GetMouseHoverWidth,
                    NULL,
                    (void*)&width,
                    SPIF.None);

                return (int)width;
            }
            set
            {
                WinApis.SystemParametersInfo(
                    SPI.SetMouseHoverWidth,
                    (uint)value,
                    NULL,
                    SPIF.SendChange);
            }
        }

        /// <summary>
        /// Gets or sets the size, in pixels, of the rectangle within which the mouse pointer has 
        /// to stay for generating mouse hover event.
        /// </summary>
        public static Size HoverSize
        {
            get
            {
                return new Size(HoverWidth, HoverHeight);
            }
            set
            {
                HoverWidth = value.Width;
                HoverHeight = value.Height;
            }
        }

        /// <summary>
        /// Gets or sets the time, in milliseconds, that the mouse pointer has to stay in the hover
        /// rectangle for generating mouse hover event.
        /// </summary>
        public unsafe static int HoverTimeOut
        {
            get
            {
                uint timeout = 0;
                WinApis.SystemParametersInfo(
                    SPI.GetMouseHoverTime,
                    NULL,
                    (void*)&timeout,
                    SPIF.None);

                return (int)timeout;
            }
            set
            {
                WinApis.SystemParametersInfo(
                    SPI.SetMouseHoverTime,
                    (uint)value,
                    NULL,
                    SPIF.SendChange);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public const int DefaultMouseSpeed = 10;

        private const uint MinimumMouseSpeed = 1;
        private const uint MaximumMouseSpeed = 20;

        /// <summary>
        /// Gets or sets the current mouse speed, between 1 (slowest) and 20 (fastest), that determines 
        /// how far the pointer will move based on the distance the mouse moves.
        /// </summary>
        public unsafe static int MouseSpeed
        {
            get
            {
                uint speed = (uint)DefaultMouseSpeed;
                WinApis.SystemParametersInfo(
                    SPI.GetMouseSpeed,
                    NULL,
                    (void*)&speed,
                    SPIF.None);

                return (int)speed;
            }
            set
            {
                WinApis.SystemParametersInfo(
                    SPI.SetMouseSpeed,
                    NULL,
                    (uint)value,
                    SPIF.SendChange);
            }
        }

        /// <summary>
        /// Gets or sets a number that indicates whether the Mouse Trails feature is enabled and the 
        /// length of the trail. If the value is zero or 1, the feature is disabled. If the value is 
        /// greater than 1, the feature is enabled and the value indicates the number of cursors drawn 
        /// in the trail.
        /// </summary>
        /// <remarks>
        /// Mouse Trails is a feature that improves the visibility of mouse cursor movements by briefly 
        /// showing a trail of cursors and quickly erasing them.
        /// </remarks>
        public unsafe static int MouseTrailsLength
        {
            get
            {
                uint length = 0;
                WinApis.SystemParametersInfo(
                    SPI.GetMouseTrails,
                    NULL,
                    (void*)&length,
                    SPIF.None);
                
                return (int)length;
            }
            set
            {
                WinApis.SystemParametersInfo(
                    SPI.SetMouseTrails,
                    (uint)value,
                    NULL,
                    SPIF.SendChange);
            }
        }

        /// <summary>
        /// Gets or sets a <see cref="bool"/> value that indicates whether the snap-to-default-button 
        /// feature is enabled.
        /// </summary>
        /// <remarks>
        /// If enabled, the mouse cursor automatically moves to the default button, such as OK or Apply,
        /// of a dialog box.
        /// </remarks>
        public static bool SnapToDefaultButton
        {
            get
            {
                bool snap = false;
                WinApis.SystemParametersInfo(
                    SPI.GetSnapToDefButton,
                    NULL,
                    ref snap,
                    SPIF.None);

                return snap;
            }
            set
            {
                WinApis.SystemParametersInfo(
                    SPI.SetSnapToDefButton,
                    value ? TRUE : FALSE,
                    NULL,
                    SPIF.SendChange);
            }
        }

        /// <summary>
        /// Gets or sets the number of characters to scroll when the horizontal mouse wheel is moved.
        /// </summary>
        public unsafe static int WheelScrollChars
        {
            get
            {
                uint chars = 3;
                WinApis.SystemParametersInfo(
                    SPI.GetWheelScrollChars,
                    NULL,
                    (void*)&chars,
                    SPIF.None);

                return (int)chars;
            }
            set
            {
                WinApis.SystemParametersInfo(
                    SPI.SetWheelScrollChars,
                    (uint)value,
                    NULL,
                    SPIF.SendChange);
            }
        }

        /// <summary>
        /// Gets or sets the number of lines to scroll when the vertical mouse wheel is moved.
        /// </summary>
        /// <remarks>
        /// The number of lines is the suggested number of lines to scroll when the mouse wheel is 
        /// rolled without using modifier keys. If the number is 0, then no scrolling should occur. 
        /// If the number of lines to scroll is greater than the number of lines viewable, and in 
        /// particular if it is <see cref="WheelPageScroll"/>, the scroll operation should be interpreted 
        /// as clicking once in the page down or page up regions of the scroll bar.
        /// </remarks>
        public unsafe static int WheelScrollLines
        {
            get
            {
                uint lines = 3;
                WinApis.SystemParametersInfo(
                    SPI.GetWheelScrollLines,
                    NULL,
                    (void*)&lines,
                    SPIF.None);

                return (int)lines;
            }
            set
            {
                WinApis.SystemParametersInfo(
                    SPI.SetWheelScrollLines,
                    (uint)value,
                    NULL,
                    SPIF.SendChange);
            }
        }

        /// <summary>
        /// Used in <see cref="WheelScrollLines"/> property to indicate scroll a page a time.
        /// </summary>
        public const int WheelPageScroll = unchecked((int)WinApis.WHEEL_PAGESCROLL);

        /// <summary>
        /// Gets or sets the double-click time for the mouse. The double-click time is the maximum 
        /// number of milliseconds that may occur between the first and second clicks of a double-click.
        /// </summary>
        public unsafe static int DoubleClickTime
        {
            get
            {
                return (int)WinApis.GetDoubleClickTime();
            }
            set
            {
                WinApis.SetDoubleClickTime((uint)value);
            }
        }
    }
}
